package com.xyht.sca_s.student_manage_system.modules.enrolStudent.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xyht.sca_s.student_manage_system.common.commonReturn.CommonCodeEnum;
import com.xyht.sca_s.student_manage_system.common.commonReturn.CommonResult;
import com.xyht.sca_s.student_manage_system.common.commonReturn.ResponseResult;
import com.xyht.sca_s.student_manage_system.modules.common.entity.SmsImportTask;
import com.xyht.sca_s.student_manage_system.modules.common.entity.SmsImportTaskDetail;
import com.xyht.sca_s.student_manage_system.modules.common.mapper.SmsImportTaskDetailMapper;
import com.xyht.sca_s.student_manage_system.modules.common.mapper.SmsImportTaskMapper;
import com.xyht.sca_s.student_manage_system.modules.enrolStudent.entity.SmsEnrolStudent;
import com.xyht.sca_s.student_manage_system.modules.enrolStudent.entity.req.SmsEnrolStudentBatchReq;
import com.xyht.sca_s.student_manage_system.modules.enrolStudent.entity.req.SmsEnrolStudentDeleteReq;
import com.xyht.sca_s.student_manage_system.modules.enrolStudent.entity.req.SmsEnrolStudentUpdateReq;
import com.xyht.sca_s.student_manage_system.modules.enrolStudent.entity.resp.SmsEnrolStudentResp;
import com.xyht.sca_s.student_manage_system.modules.enrolStudent.mapper.SmsEnrolStudentMapper;
import com.xyht.sca_s.student_manage_system.modules.enrolStudent.service.SmsEnrolStudentService;
import org.springframework.beans.BeanUtils;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Future;
import java.util.stream.Collectors;

import static com.xyht.sca_s.student_manage_system.common.util.ParamCheckUtil.isNullOrEmpty;
import static com.xyht.sca_s.student_manage_system.modules.common.constant.TaskDetailReason.REASON_IMPORT_ERR;
import static com.xyht.sca_s.student_manage_system.modules.common.constant.TaskDetailReason.REASON_INVALID_PARAM;
import static com.xyht.sca_s.student_manage_system.modules.common.constant.TaskNameExample.TASK_NAME_ENROL_STUDENT;
import static com.xyht.sca_s.student_manage_system.modules.common.constant.TaskStatus.TASK_STATUS_DONE;
import static com.xyht.sca_s.student_manage_system.modules.common.constant.TaskStatus.TASK_STATUS_ERR;
import static com.xyht.sca_s.student_manage_system.modules.common.constant.TaskTypeConstant.TASK_TYPE_ENROL_STUDENT;

/**
 * <p>
 * 招生信息表 服务实现类
 * </p>
 *
 * @author XYHT
 * @since 2023-08-31
 */
@Service
public class SmsEnrolStudentServiceImpl extends ServiceImpl<SmsEnrolStudentMapper, SmsEnrolStudent> implements SmsEnrolStudentService {

    @Resource
    private SmsImportTaskMapper smsImportTaskMapper;
    @Resource
    SmsImportTaskDetailMapper smsImportTaskDetailMapper;
    @Resource
    private SmsEnrolStudentMapper smsEnrolStudentMapper;
    @Resource
    PlatformTransactionManager transactionManager;


    @Override
    @Async
    public Future<ResponseResult> batchAddEnrolStudent(Map<String, Object> map, String user_id) {
        JSONObject jsonObject = JSONObject.parseObject(JSON.toJSONString(map));
        List<SmsEnrolStudentBatchReq> enrolStudentList = JSONObject.parseArray(JSON.toJSONString(jsonObject.get("list")), SmsEnrolStudentBatchReq.class);
        if (enrolStudentList == null || enrolStudentList.size() < 1) {
            return new AsyncResult<>(CommonResult.failed(CommonCodeEnum.INVALID_PARAM));
        }

        //创建导入任务
        SmsImportTask smsImportTask = new SmsImportTask();
        smsImportTask.setTaskName(TASK_NAME_ENROL_STUDENT);
        smsImportTask.setUserId(user_id);
        smsImportTask.setTaskType(TASK_TYPE_ENROL_STUDENT);
        smsImportTaskMapper.insert(smsImportTask);
        batchAddEnrolStudentInfo(enrolStudentList, smsImportTask.getId());
        return new AsyncResult<>(CommonResult.success());
    }

    @Override
    public ResponseResult deleteEnrolStudentInfo(SmsEnrolStudentDeleteReq deleteReq) {
        if(deleteReq.getStudentId() == null || deleteReq.getStudentId().size() < 1){
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }
        for (String studentId : deleteReq.getStudentId()) {
            SmsEnrolStudent enrolStudent = smsEnrolStudentMapper.selectById(studentId);
            if(enrolStudent == null){
                return CommonResult.failed(CommonCodeEnum.ENROL_STUDENT_NOT_EXIST);
            }
        }
        smsEnrolStudentMapper.deleteBatchIds(deleteReq.getStudentId());
        return CommonResult.success();
    }

    @Override
    public ResponseResult addEnrolStudentInfo(SmsEnrolStudentBatchReq addReq) {
        if(isNullOrEmpty(addReq.getName(),addReq.getSex(),addReq.getIdCard(),addReq.getOrigin(),addReq.getNation(),addReq.getCollege())){
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }
        if(addReq.getIdCard().length() != 18){
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }
        String idCard = addReq.getIdCard();
        String birthYear = idCard.substring(6, 10);
        SmsEnrolStudent addEnrolStudent = new SmsEnrolStudent();
        BeanUtils.copyProperties(addReq,addEnrolStudent);
        addEnrolStudent.setBirthYear(birthYear);
        smsEnrolStudentMapper.insert(addEnrolStudent);
        return CommonResult.success();

    }

    @Override
    public ResponseResult updateEnrolStudentInfo(SmsEnrolStudentUpdateReq updateReq) {
        if(isNullOrEmpty(updateReq.getId())){
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }
        if(isNullOrEmpty(updateReq.getName(),updateReq.getSex(),updateReq.getIdCard(),updateReq.getOrigin(),updateReq.getNation(),updateReq.getCollege())){
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }
        SmsEnrolStudent smsEnrolStudent = smsEnrolStudentMapper.selectById(updateReq.getId());
        if(smsEnrolStudent == null){
            return CommonResult.failed(CommonCodeEnum.ENROL_STUDENT_NOT_EXIST);
        }
        BeanUtils.copyProperties(updateReq,smsEnrolStudent);
        smsEnrolStudentMapper.updateById(smsEnrolStudent);
        return CommonResult.success();
    }

    @Override
    public ResponseResult getEnrolStudentInfoById(String id) {
        if(isNullOrEmpty(id)){
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }
        SmsEnrolStudent smsEnrolStudent = smsEnrolStudentMapper.selectById(id);
        if(smsEnrolStudent == null){
            return CommonResult.failed(CommonCodeEnum.ENROL_STUDENT_NOT_EXIST);
        }
        SmsEnrolStudentResp studentResp = new SmsEnrolStudentResp();
        BeanUtils.copyProperties(smsEnrolStudent,studentResp);
        return CommonResult.success(studentResp);
    }

    @Override
    public ResponseResult getEnrolStudentInfoList(Integer pageNum, Integer pageSize, String name, String idCard, Integer sex, String origin,String nation, String college) {
        Page<SmsEnrolStudent> page = new Page<>(pageNum,pageSize);
        LambdaQueryWrapper<SmsEnrolStudent> queryWrapper = new LambdaQueryWrapper<>();
        if(!isNullOrEmpty(name)){
            queryWrapper.like(SmsEnrolStudent::getName,name);
        }
        if(!isNullOrEmpty(idCard)){
            queryWrapper.eq(SmsEnrolStudent::getIdCard,idCard);
        }
        if(!isNullOrEmpty(sex)){
            queryWrapper.eq(SmsEnrolStudent::getSex,sex);
        }
        if(!isNullOrEmpty(origin)){
            queryWrapper.like(SmsEnrolStudent::getOrigin,origin);
        }
        if(!isNullOrEmpty(nation)){
            queryWrapper.like(SmsEnrolStudent::getNation,nation);
        }
        if(!isNullOrEmpty(college)){
            queryWrapper.like(SmsEnrolStudent::getCollege,college);
        }
        smsEnrolStudentMapper.selectPage(page,queryWrapper);
        List<SmsEnrolStudentResp> list = new ArrayList<>();
        list = page.getRecords()
                .stream()
                .map(enrolStudent ->{
                    SmsEnrolStudentResp studentResp = new SmsEnrolStudentResp();
                    BeanUtils.copyProperties(enrolStudent,studentResp);
                    return studentResp;
                })
                .collect(Collectors.toList());
        int total = (int)page.getTotal();
        return CommonResult.success(list,total);
    }

    private void batchAddEnrolStudentInfo(List<SmsEnrolStudentBatchReq> enrolStudentList, String id) {
        int OFFSET_ROW = 1;
        int task_status = TASK_STATUS_DONE;
        for (int i = 0; i < enrolStudentList.size(); i++) {
            //开启事务
            DefaultTransactionDefinition dt = new DefaultTransactionDefinition();
            // 嵌套事务 PROPAGATION_REQUIRES_NEW 每次开启一个新的事务
            dt.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
            // 设置嵌套事务
            TransactionStatus status = transactionManager.getTransaction(dt);
            try {
                SmsEnrolStudentBatchReq storage = enrolStudentList.get(i);
                if (isNullOrEmpty(storage.getName(),storage.getSex(),storage.getIdCard(),storage.getOrigin(),storage.getCollege(),storage.getNation())) {
                    transactionManager.rollback(status);
                    task_status = TASK_STATUS_ERR;
                    createTeacherImportTaskDetail(id, REASON_INVALID_PARAM, (i + OFFSET_ROW) + "");
                    continue;
                }
                SmsEnrolStudent addEnrolStudent = new SmsEnrolStudent();
                BeanUtils.copyProperties(storage,addEnrolStudent);
                if(storage.getIdCard().length() != 18){
                    transactionManager.rollback(status);
                    task_status = TASK_STATUS_ERR;
                    createTeacherImportTaskDetail(id, REASON_INVALID_PARAM, (i + OFFSET_ROW) + "");
                    continue;
                }
                String idCard = storage.getIdCard();
                String birthYear = idCard.substring(6, 10);
                addEnrolStudent.setBirthYear(birthYear);
                smsEnrolStudentMapper.insert(addEnrolStudent);
                transactionManager.commit(status);
            } catch (Exception e) {
                transactionManager.rollback(status);
                task_status = TASK_STATUS_ERR;
                createTeacherImportTaskDetail(id, REASON_IMPORT_ERR, (i + OFFSET_ROW) + "");
            }finally {
                if (status.isNewTransaction() && !status.isCompleted()) {
                    transactionManager.commit(status);
                }
            }
        }
        SmsImportTask smsImportTask = new SmsImportTask();
        smsImportTask.setId(id);
        smsImportTask.setStatus(task_status);
        smsImportTaskMapper.updateById(smsImportTask);
    }

    private void createTeacherImportTaskDetail(String id, String reason, String row) {
        SmsImportTaskDetail smsImportTaskDetail = new SmsImportTaskDetail();
        smsImportTaskDetail.setTaskId(id);
        smsImportTaskDetail.setFailReason(reason);
        smsImportTaskDetail.setFailRow(row);
        smsImportTaskDetailMapper.insert(smsImportTaskDetail);
    }
}
